<template>
  <div class="max-w-4xl mx-auto p-6">
    <h1 class="text-2xl font-bold mb-4">屏幕录制（在线）</h1>

    <div class="bg-white shadow rounded p-4 mb-6">
      <div class="flex items-center space-x-4 mb-4">
        <label class="inline-flex items-center">
          <input type="checkbox" v-model="includeMic" class="form-checkbox h-5 w-5 text-blue-600" />
          <span class="ml-2 text-gray-700">包含麦克风音频</span>
        </label>
      </div>

      <div class="flex space-x-3 mb-4">
        <button @click="start" :disabled="isRecording" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50">开始录制</button>
        <button @click="stop" :disabled="!isRecording" class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50">停止</button>
        <button @click="pause" :disabled="!isRecording || isPaused" class="px-4 py-2 bg-yellow-500 text-white rounded hover:bg-yellow-600 disabled:opacity-50">暂停</button>
        <button @click="resume" :disabled="!isRecording || !isPaused" class="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700 disabled:opacity-50">继续</button>
        <button @click="download" :disabled="!recordedBlob" class="px-4 py-2 bg-gray-700 text-white rounded hover:bg-gray-800 disabled:opacity-50">下载</button>
      </div>

      <p class="text-sm text-gray-600 mb-2">说明：录屏使用浏览器的 MediaRecorder 与 getDisplayMedia API。若需要麦克风声音，请允许麦克风访问。</p>

      <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
        <div>
          <h3 class="text-sm font-medium text-gray-700 mb-2">实时预览</h3>
          <video ref="liveVideo" autoplay playsinline muted class="w-full bg-black rounded"></video>
        </div>

        <div>
          <h3 class="text-sm font-medium text-gray-700 mb-2">录制回放</h3>
          <video v-if="recordedBlobUrl" :src="recordedBlobUrl" controls class="w-full bg-black rounded"></video>
          <div v-else class="w-full h-48 bg-gray-50 rounded flex items-center justify-center text-gray-400">还没有录制内容</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from 'vue'

const includeMic = ref(false)
const isRecording = ref(false)
const isPaused = ref(false)
const liveVideo = ref(null)

let mediaRecorder = null
let recordedChunks = []
let localStream = null
const recordedBlob = ref(null)
const recordedBlobUrl = ref(null)

async function start() {
  try {
    // 请求屏幕流
    const displayStream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true })

    // 可选麦克风
    let audioStream = null
    if (includeMic.value) {
      try {
        audioStream = await navigator.mediaDevices.getUserMedia({ audio: true })
      } catch (e) {
        // 如果用户拒绝麦克风，继续仅使用系统音频（如果有）
        console.warn('麦克风不可用或被拒绝：', e)
      }
    }

    // 合并轨道：优先使用麦克风音轨，如果没有就使用 displayStream 的音轨（系统音）
    const tracks = []
    displayStream.getVideoTracks().forEach(t => tracks.push(t))
    if (audioStream && audioStream.getAudioTracks().length) {
      audioStream.getAudioTracks().forEach(t => tracks.push(t))
    } else if (displayStream.getAudioTracks().length) {
      displayStream.getAudioTracks().forEach(t => tracks.push(t))
    }

    localStream = new MediaStream(tracks)

    // 预览实时流（静音防止回声）
    if (liveVideo.value) {
      liveVideo.value.srcObject = localStream
    }

    recordedChunks = []
    mediaRecorder = new MediaRecorder(localStream, { mimeType: 'video/webm;codecs=vp9,opus' })

    mediaRecorder.ondataavailable = (e) => {
      if (e.data && e.data.size > 0) recordedChunks.push(e.data)
    }

    mediaRecorder.onstop = () => {
      const blob = new Blob(recordedChunks, { type: 'video/webm' })
      recordedBlob.value = blob
      if (recordedBlobUrl.value) URL.revokeObjectURL(recordedBlobUrl.value)
      recordedBlobUrl.value = URL.createObjectURL(blob)
      // 停止所有轨道
      stopLocalTracks()
    }

    mediaRecorder.start(100) // 收集片段
    isRecording.value = true
    isPaused.value = false
  } catch (err) {
    console.error('开始录制失败：', err)
    alert('无法开始录制：' + (err && err.message ? err.message : err))
  }
}

function pause() {
  if (mediaRecorder && mediaRecorder.state === 'recording') {
    mediaRecorder.pause()
    isPaused.value = true
  }
}

function resume() {
  if (mediaRecorder && mediaRecorder.state === 'paused') {
    mediaRecorder.resume()
    isPaused.value = false
  }
}

function stopLocalTracks() {
  if (localStream) {
    localStream.getTracks().forEach(t => t.stop())
    localStream = null
  }
  if (liveVideo.value) {
    try { liveVideo.value.srcObject = null } catch (e) {}
  }
  isRecording.value = false
  isPaused.value = false
}

function stop() {
  if (mediaRecorder && (mediaRecorder.state === 'recording' || mediaRecorder.state === 'paused')) {
    mediaRecorder.stop()
    mediaRecorder = null
  } else {
    stopLocalTracks()
  }
}

function download() {
  if (!recordedBlob.value) return
  const a = document.createElement('a')
  a.href = recordedBlobUrl.value
  a.download = `recording_${new Date().toISOString().replace(/[:.]/g,'-')}.webm`
  document.body.appendChild(a)
  a.click()
  a.remove()
}

onUnmounted(() => {
  stopLocalTracks()
  if (recordedBlobUrl.value) URL.revokeObjectURL(recordedBlobUrl.value)
})

</script>

<style scoped>
.form-checkbox { appearance: none; }
</style>
